﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "ElevationViewSymbolNewBehaviors.h"
#include "ElevationViewSymbolNew.h"

#include "AlgorithmProject.h"
#include "AuxiliaryElementUtils.h"
#include "DbObjectUtils.h"
#include "GbmpBuiltInCategoryUniIdentitiesNew.h"
#include "GbmpCalculatorBase.h"
#include "GbmpModelViewTypes.h"
#include "GcmpBuiltInCategoryUniIdentities.h"
#include "GcmpBuiltInParameterDefinitions.h"
#include "GraphicsRenderLayer.h"
#include "ICalculator.h"
#include "ICalculatorCollection.h"
#include "IDocument.h"
#include "IElement.h"
#include "IElementModelShape.h"
#include "IElementMoveContext.h"
#include "IElementParameters.h"
#include "IElementParentReporter.h"
#include "IElementPositionPoints.h"
#include "IElementStatus.h"
#include "IGenericElement.h"
#include "IGraphicsElementShape.h"
#include "IGraphicsLine.h"
#include "IGraphicsPoint.h"
#include "IGraphicsStyleManager.h"
#include "IModelView.h"
#include "IViewClipRange.h"
#include "IParameter.h"
#include "IParameterDefinitionLibrary.h"
#include "IPlane.h"
#include "IRegenerator.h"
#include "RegenDataId.h"
#include "Vector3dUtils.h"
#include "NdbUpgrade.h"
#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"

using namespace gcmp;

namespace
{
    const ElevationViewSymbolNew* GetElevationViewSymbolByOwnerElement(const IElement* pElevationViewSymbolOwnerElement)
    {
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pElevationViewSymbolOwnerElement != nullptr, L"Invalid pOwnerElement",L"GDMPLab",L"2024-03-30");

        const IGenericElement* pGenericElement = quick_cast<IGenericElement>(pElevationViewSymbolOwnerElement);
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pGenericElement != nullptr, L"Invalid pGenericElement",L"GDMPLab",L"2024-03-30");

         return (quick_cast<ElevationViewSymbolNew>(pGenericElement->GetExternalObject()));
    }

    ElevationViewSymbolNew* GetElevationViewSymbolByOwnerElementFW(IElement* pElevationViewSymbolOwnerElement)
    {
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pElevationViewSymbolOwnerElement != nullptr, L"Invalid pOwnerElement",L"GDMPLab",L"2024-03-30");

        IGenericElement* pGenericElement = quick_cast<IGenericElement>(pElevationViewSymbolOwnerElement);
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pGenericElement != nullptr, L"Invalid pGenericElement",L"GDMPLab",L"2024-03-30");

        return (quick_cast<ElevationViewSymbolNew>(pGenericElement->GetExternalObject()));
    }

    IModelView* GetElevationModelViewByElevationViewSymbolOwnerElement(const IElement* pElevationViewSymbolOwnerElement)
    {
        const ElevationViewSymbolNew *pElevatoinViewSymbol = GetElevationViewSymbolByOwnerElement(pElevationViewSymbolOwnerElement);
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pElevatoinViewSymbol != nullptr, L"Invalid pElevatoinViewSymbol",L"GDMPLab",L"2024-03-30");

        return pElevatoinViewSymbol->GetElevationModelView();
    }
}

namespace gcmp
{
    // 夹点位置更新计算器
    class ElevationViewSymbolNewGripPointPositionCalculator : public GbmpCalculatorBase
    {
        DECLARE_CALCULATOR(ElevationViewSymbolNewGripPointPositionCalculator, IElementShapeHandle)
    public:
        ElevationViewSymbolNewGripPointPositionCalculator(IDocument* pDoc, const RegenDataId& outputDataId) : GbmpCalculatorBase(pDoc, outputDataId) {}
        virtual void ReportInputDataIds(std::vector<RegenDataId> & dataIds) const override;
        virtual void Execute() override;
    };

    // 切割线位置更新计算器
    class ElevationViewSymbolNewBorderCalculator : public gcmp::GbmpCalculatorBase
    {
        DECLARE_CALCULATOR(ElevationViewSymbolNewBorderCalculator, IElementShapeHandle)
    public:
        ElevationViewSymbolNewBorderCalculator(IDocument* pDoc, const RegenDataId& outputDataId) : GbmpCalculatorBase(pDoc, outputDataId) {}
        virtual void ReportInputDataIds(std::vector<RegenDataId> & dataIds) const override;
        virtual void Execute() override;
    };

    // 立面视图标记更新计算器
    class ElevationViewSymbolNewRegenerationCalculator : public GbmpCalculatorBase
    {
        DECLARE_CALCULATOR(ElevationViewSymbolNewRegenerationCalculator, IElement)
    public:
        ElevationViewSymbolNewRegenerationCalculator(IDocument* pDoc, const RegenDataId& outputDataId) : GbmpCalculatorBase(pDoc, outputDataId) {}
        virtual void ReportInputDataIds(std::vector<RegenDataId> & dataIds) const override;
        virtual void Execute() override;
    };
}


#pragma region BorderCalculator
IMPLEMENT_CALCULATOR_CREATOR(gcmp, ElevationViewSymbolNewBorderCalculator);

void ElevationViewSymbolNewBorderCalculator::ReportInputDataIds(std::vector<RegenDataId> & dataIds) const
{
    IElementShapeHandle* pElementShapeHandle = GetElement<IElementShapeHandle>();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pElementShapeHandle, L"invalid pElementShapeHandle",L"GDMPLab",L"2024-03-30");

    dataIds.push_back(pElementShapeHandle->GetMasterIdRdIdForBehavior());
    dataIds.push_back(pElementShapeHandle->GetShapeHandlePositionIndexInMasterElementRdId());

    IDocument * pDoc = pElementShapeHandle->GetDocument();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDoc, L"invalid pDoc",L"GDMPLab",L"2024-03-30");
    IElement* pMasterElem = pDoc->GetElement(pElementShapeHandle->GetMasterId());
    DBG_WARN_AND_RETURN_VOID_UNLESS(pMasterElem, L"invalid pMasterElement",L"GDMPLab",L"2024-03-30");

    const ElevationViewSymbolNew *pSymbol = GetElevationViewSymbolByOwnerElement(pMasterElem);
    dataIds.push_back(pSymbol->GetModelViewRangeUpdatedRdId());
}

void ElevationViewSymbolNewBorderCalculator::Execute()
{
    IElementShapeHandle* pElementShapeHandle = GetElement<IElementShapeHandle>();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pElementShapeHandle, L"invalid pElementShapeHandle",L"GDMPLab",L"2024-03-30");

    IDocument *pDoc = this->GetDocument();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDoc, L"invalid pDoc",L"GDMPLab",L"2024-03-30");
    IElement* pElement = pDoc->GetElement(pElementShapeHandle->GetMasterId());
    DBG_WARN_AND_RETURN_VOID_UNLESS(pElement, L"invalid pElement",L"GDMPLab",L"2024-03-30");
    // The host may have been deleted via undo/redo
    if (nullptr == pElement)
    {
        return;
    }

    IElementShapeHandleBehavior* pElementShapeHandleBehavior = pElementShapeHandle->GetElementShapeHandleBehavior();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pElementShapeHandleBehavior, L"invalid pElementShapeHandleBehavior为空",L"GDMPLab",L"2024-03-30");
    pElementShapeHandleBehavior->UpdatePosition();
}
#pragma endregion BorderCalculator

#pragma region GripPointPositionCalculator
IMPLEMENT_CALCULATOR_CREATOR(gcmp, ElevationViewSymbolNewGripPointPositionCalculator);

void ElevationViewSymbolNewGripPointPositionCalculator::ReportInputDataIds(std::vector<RegenDataId> & dataIds) const
{
    IElementShapeHandle* pElementShapeHandle = GetElement<IElementShapeHandle>();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pElementShapeHandle, L"invalid pElementShapeHandle",L"GDMPLab",L"2024-03-30");

    dataIds.push_back(pElementShapeHandle->GetMasterIdRdIdForBehavior());
    dataIds.push_back(pElementShapeHandle->GetShapeHandlePositionIndexInMasterElementRdId());

    IDocument * pDoc = pElementShapeHandle->GetDocument();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDoc, L"invalid pDoc",L"GDMPLab",L"2024-03-30");
    IElement* pMasterElem = pDoc->GetElement(pElementShapeHandle->GetMasterId());
    DBG_WARN_AND_RETURN_VOID_UNLESS(pMasterElem, L"invalid pMasterElement",L"GDMPLab",L"2024-03-30");
    const IElementModelShape *pElementShape = pMasterElem->GetElementModelShape();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pElementShape, L"invalid pElementShape",L"GDMPLab",L"2024-03-30");
    dataIds.push_back(pElementShape->GetGraphicsElementShapeRdId());

    const ElevationViewSymbolNew *pSymbol = GetElevationViewSymbolByOwnerElement(pMasterElem);
    dataIds.push_back(pSymbol->GetModelViewRangeUpdatedRdId());
}

void ElevationViewSymbolNewGripPointPositionCalculator::Execute()
{
    IElementShapeHandle* pElementShapeHandle = GetElement<IElementShapeHandle>();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pElementShapeHandle, L"invalid pElementShapeHandle",L"GDMPLab",L"2024-03-30");

    IDocument *pDoc = this->GetDocument();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDoc, L"invalid pDoc",L"GDMPLab",L"2024-03-30");

    IElement* pElement = pDoc->GetElement(pElementShapeHandle->GetMasterId());
    DBG_WARN_AND_RETURN_VOID_UNLESS(pElement, L"invalid pElement",L"GDMPLab",L"2024-03-30");
    // The host may have been deleted via undo/redo
    if (nullptr == pElement)
    {
        return;
    }

    IElementShapeHandleBehavior* pElementShapeHandleBehavior = pElementShapeHandle->GetElementShapeHandleBehavior();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pElementShapeHandleBehavior, L"invalid pElementShapeHandleBehavior为空",L"GDMPLab",L"2024-03-30");
    pElementShapeHandleBehavior->UpdatePosition();
}

#pragma endregion GripPointPositionCalculator

#pragma region RegenerationCalculator
IMPLEMENT_CALCULATOR_CREATOR(gcmp, ElevationViewSymbolNewRegenerationCalculator);

void ElevationViewSymbolNewRegenerationCalculator::ReportInputDataIds(std::vector<RegenDataId> & dataIds) const
{
    IGenericElement* pOwnerElement = GetElement<IGenericElement>();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pOwnerElement, L"invalid pOwnerElement",L"GDMPLab",L"2024-03-30");

    IModelView *pModelView = GetElevationModelViewByElevationViewSymbolOwnerElement(pOwnerElement);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pModelView, L"pModelView is null",L"GDMPLab",L"2024-03-30");
    dataIds.push_back(pModelView->GetOriginRdId());
    dataIds.push_back(pModelView->GetViewDirectionRdId());
    dataIds.push_back(pModelView->GetRightDirectionRdId());
    dataIds.push_back(pModelView->GetUpDirectionRdId());
    dataIds.push_back(pModelView->GetRangeUpdatedRdId());
}

void ElevationViewSymbolNewRegenerationCalculator::Execute()
{
    IGenericElement* pOwnerElement = GetElement<IGenericElement>();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pOwnerElement, L"invalid pOwnerElement",L"GDMPLab",L"2024-03-30");

    ElevationViewSymbolNew *pElevationSymbol = GetElevationViewSymbolByOwnerElementFW(pOwnerElement);
    pElevationSymbol->MarkModelViewRangeUpdatedRdId();
}
#pragma endregion RegenerationCalculator

#pragma region BorderBehavior
DBOBJECT_DATA_DEFINE(ElevationViewSymbolNewBorderBehavior)
{
    m_Document = nullptr;
}

ElevationViewSymbolNewBorderBehavior::ElevationViewSymbolNewBorderBehavior(IDocument* pDoc, const ElementId& modelViewId)
    :m_Document(pDoc), m_ModelViewId(modelViewId)
{

}

IElementShapeHandle* ElevationViewSymbolNewBorderBehavior::GetElementShapeHandle() const
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(m_Document, L"invalid pDocument",L"GDMPLab",L"2024-03-30");
    return quick_cast<IElementShapeHandle>(m_Document->GetElement(m_ElementShapeHandleId));
}

IElement * ElevationViewSymbolNewBorderBehavior::GetMasterElement() const
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(m_Document, L"invalid pDocument",L"GDMPLab",L"2024-03-30");

    IElementShapeHandle *pElementShapeHandle = GetElementShapeHandle();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pElementShapeHandle, L"invalid pElementShapeHandle",L"GDMPLab",L"2024-03-30");

    return m_Document->GetElement(pElementShapeHandle->GetMasterId());
}

OwnerPtr<IElementShapeHandleBehavior> ElevationViewSymbolNewBorderBehavior::Create(IDocument* pDoc, const ElementId& modelViewId)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc && modelViewId.IsValid(), L"invalid parameter",L"GDMPLab",L"2024-03-30");
    return NEW_AS_OWNER_PTR(ElevationViewSymbolNewBorderBehavior, pDoc, modelViewId);
}

void ElevationViewSymbolNewBorderBehavior::GetCalculators(ICalculatorCollection* calculators) const
{
    IElementShapeHandle* pElementShapeHandle = GetElementShapeHandle();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pElementShapeHandle != nullptr, L"invalid pElementShapeHandle",L"GDMPLab",L"2024-03-30");

    ADD_CALCULATOR(ElevationViewSymbolNewBorderCalculator, pElementShapeHandle->GetDocument(), pElementShapeHandle->GetPositionRdIdForBehavior());
}

bool ElevationViewSymbolNewBorderBehavior::Translate(const IElementMoveContext & moveContext)
{
    return true;
}

OwnerPtr<IGraphicsElementShape> ElevationViewSymbolNewBorderBehavior::CreateGrahicsElementShapeInModelView(const IModelView* pModelView) const
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pModelView != nullptr, L"invalid pModelView",L"GDMPLab",L"2024-03-30");

    if (PlanViewType != pModelView->GetUserDataId())
        return nullptr;
    //获取水平面
    OwnerPtr<IPlane> opWorkPlane = pModelView->GetWorkPlane();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(opWorkPlane != nullptr, L"invalid opWorkPlane",L"GDMPLab",L"2024-03-30");

    IElement *pMasterElement = GetMasterElement();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pMasterElement != nullptr, L"invalid pMasterElement",L"GDMPLab",L"2024-03-30");

    //获取立面
    IModelView *pElevationModelView = GetElevationModelViewByElevationViewSymbolOwnerElement(pMasterElement);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pElevationModelView, L"invalid pElevationModelView",L"GDMPLab",L"2024-03-30");
    IViewClipRange* pViewClipRange = IViewClipRange::GetViewClipRange(pElevationModelView->GetDocument(), pElevationModelView->GetViewClipRangeId());
    //获取立面视图的视点与视图方向（投影至水平面）
    Vector2d uvParameter;
    Vector3d tmpViewPoint3d = pElevationModelView->GetOrigin();
    Vector3d tmpDir3d = pElevationModelView->GetViewDirection();
    Vector3d elevationViewPoint;
    AlgorithmProject::Project(tmpViewPoint3d, opWorkPlane.get(), uvParameter, elevationViewPoint);
    
    Vector3d projectedPoint;
    AlgorithmProject::Project(tmpDir3d, opWorkPlane.get(), uvParameter, projectedPoint);
    Vector3d elevationViewDir(projectedPoint.Vec2d(), 0);
    elevationViewDir.Normalize();

    //获取立面视图剖切框的左、右偏移
    double viewPortLeftOffset;
    double viewPortRightOffset;
    double uselessOffset;
    {
        bool bOk = pViewClipRange->GetRectViewClipRange(viewPortLeftOffset, viewPortRightOffset, uselessOffset, uselessOffset);
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(bOk, L"Fail GetDefaultRectViewport",L"GDMPLab",L"2024-03-30");
    }

    //计算立面视图剖切框的左、右端点位置（在水平面上的）
    Vector3d leftPoint = elevationViewPoint + (Vector3dUtils::RotateVectorAroundAxis(elevationViewDir, -pModelView->GetViewDirection(), Constants::MATH_PI_2))*viewPortLeftOffset;
    Vector3d rightPoint = elevationViewPoint + (Vector3dUtils::RotateVectorAroundAxis(elevationViewDir, -pModelView->GetViewDirection(), -Constants::MATH_PI_2))*viewPortRightOffset;

    //创建辅助线并设置样式
    OwnerPtr<IGraphicsLine> opLine = IGraphicsLine::Create(leftPoint, rightPoint);
    IGraphicsStyleManager* pStyleManager = GetDocument()->GetGraphicsStyleManager();
    if (pStyleManager)
    {
        opLine->SetGraphicsStyleId(pStyleManager->GetGraphicsStyleIdByCategoryUid(BuiltInCategoryUniIdentities::BICU_VIEW_SYMBOL_AUXILIARY_BORDER));
    }

    OwnerPtr<IGraphicsElementShape> opGGrepNodeRoot = IGraphicsElementShape::Create(GraphicsRenderLayer::TransientObject);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(opGGrepNodeRoot != nullptr, L"invalid opGGrepNodeRoot",L"GDMPLab",L"2024-03-30");
    opGGrepNodeRoot->AddChild(TransferOwnership(opLine));

    IElementShapeHandle *pElementShapeHandle = GetElementShapeHandle();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pElementShapeHandle, L"invalid pElementShapeHandle",L"GDMPLab",L"2024-03-30");
    opGGrepNodeRoot->SetElementId(pElementShapeHandle->GetElementId());
    opGGrepNodeRoot->SetIsClippable(false);

    return opGGrepNodeRoot;
}

void ElevationViewSymbolNewBorderBehavior::ReportParents(IElementParentReporter& reporter) const
{
    reporter.ReportWeak(GetModelViewId());
}

void ElevationViewSymbolNewBorderBehavior::UpdatePosition()
{
    IElementShapeHandle* pElementShapeHandle = GetElementShapeHandle();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pElementShapeHandle != nullptr, L"invalid pElementShapeHandle",L"GDMPLab",L"2024-03-30");

    const IElement* pOwnerElement = GetMasterElement();

    //注：这里必须调用const版本的pOwnerElement，否则会引起事务外修改Element的DBG_WARN
    const IElementPositionPoints* pPositionPoints = pOwnerElement->GetPositionPoints();
    if (pPositionPoints)
    {
        int positionIndex = pElementShapeHandle->GetPositionIndexInMasterElement();
        Vector3d pos = pPositionPoints->GetControlPoint(positionIndex);
        pElementShapeHandle->SetPosition(pos);
    }
}

void ElevationViewSymbolNewBorderBehavior::GetNearestPoint(Vector3d& nearPoint) const
{
    IElementShapeHandle* pElementShapeHandle = GetElementShapeHandle();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pElementShapeHandle != nullptr, L"invalid pElementShapeHandle",L"GDMPLab",L"2024-03-30");
    nearPoint = pElementShapeHandle->GetPosition();
}

bool ElevationViewSymbolNewBorderBehavior::GetHandleCommandString(const IObject* commandEnvironment, std::wstring& commandStr, CommandParameters& cmdParams) const\
{
    return false;
}
#pragma endregion BorderBehavior

#pragma region GripPointBehavior
DBOBJECT_DATA_DEFINE(ElevationViewSymbolNewGripPointBehavior)
{
    m_Document = nullptr;
}

ElevationViewSymbolNewGripPointBehavior::ElevationViewSymbolNewGripPointBehavior(IDocument* pDoc, const ElementId& modelViewId)
    :m_Document(pDoc), m_ModelViewId(modelViewId)
{

}

IElementShapeHandle* ElevationViewSymbolNewGripPointBehavior::GetElementShapeHandle() const
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(m_Document, L"invalid pDocument",L"GDMPLab",L"2024-03-30");
    return quick_cast<IElementShapeHandle>(m_Document->GetElement(m_ElementShapeHandleId));
}

IElement * ElevationViewSymbolNewGripPointBehavior::GetMasterElement() const
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(m_Document, L"invalid pDocument",L"GDMPLab",L"2024-03-30");

    IElementShapeHandle *pElementShapeHandle = GetElementShapeHandle();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pElementShapeHandle, L"invalid pElementShapeHandle",L"GDMPLab",L"2024-03-30");

    return m_Document->GetElement(pElementShapeHandle->GetMasterId());
}

OwnerPtr<IElementShapeHandleBehavior> ElevationViewSymbolNewGripPointBehavior::Create(IDocument* pDoc, const ElementId& modelViewId)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc && modelViewId.IsValid(), L"invalid parameter",L"GDMPLab",L"2024-03-30");
    return NEW_AS_OWNER_PTR(ElevationViewSymbolNewGripPointBehavior, pDoc, modelViewId);
}

void ElevationViewSymbolNewGripPointBehavior::GetCalculators(ICalculatorCollection* calculators) const
{
    IElementShapeHandle* pElementShapeHandle = GetElementShapeHandle();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pElementShapeHandle != nullptr, L"invalid pElementShapeHandle",L"GDMPLab",L"2024-03-30");

    ADD_CALCULATOR(ElevationViewSymbolNewGripPointPositionCalculator, pElementShapeHandle->GetDocument(), pElementShapeHandle->GetPositionRdIdForBehavior());
}

bool ElevationViewSymbolNewGripPointBehavior::Translate(const IElementMoveContext & moveContext)
{
    IElementShapeHandle* pElementShapeHandle = GetElementShapeHandle();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pElementShapeHandle != nullptr, L"invalid pElementShapeHandle",L"GDMPLab",L"2024-03-30");

    IElement *pOwnerElement = GetMasterElement();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pOwnerElement, L"invalid pOwnerElement",L"GDMPLab",L"2024-03-30");

    IElementPositionPoints *pOwnerElementPosPoint = pOwnerElement->GetPositionPoints();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pOwnerElementPosPoint, L"invalid pOwnerElementPosPoint",L"GDMPLab",L"2024-03-30");

    int positionIndex = pElementShapeHandle->GetPositionIndexInMasterElement();

    Vector3d pos = pOwnerElementPosPoint->GetControlPoint(positionIndex);
    pOwnerElementPosPoint->SetControlPoint(positionIndex, pos + moveContext.GetMoveVector());

    //触发所有辅助对象关联更新
    std::vector<ElementId> vecGripPointIds = AuxiliaryElementUtils::GetAuxiliaryElements(pOwnerElement);
    return pOwnerElement->GetDocument()->GetRegenerator()->ForceRegeneratingElements(vecGripPointIds);
}

OwnerPtr<IGraphicsElementShape> ElevationViewSymbolNewGripPointBehavior::CreateGrahicsElementShapeInModelView(const IModelView* pModelView) const
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pModelView != nullptr, L"invalid pModelView",L"GDMPLab",L"2024-03-30");

    if (PlanViewType != pModelView->GetUserDataId())
        return nullptr;

    IElementShapeHandle* pElementShapeHandle = GetElementShapeHandle();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pElementShapeHandle != nullptr, L"invalid pElementShapeHandle",L"GDMPLab",L"2024-03-30");

    OwnerPtr<IPlane> opWorkPlane = pModelView->GetWorkPlane();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(opWorkPlane != nullptr, L"invalid opWorkPlane",L"GDMPLab",L"2024-03-30");

    // 更新GRep
    OwnerPtr<IGraphicsElementShape> opGGrepNodeRoot = IGraphicsElementShape::Create(GraphicsRenderLayer::TransientObject);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(opGGrepNodeRoot != nullptr, L"invalid opGGrepNodeRoot",L"GDMPLab",L"2024-03-30");

    Vector2d uvParameter;
    Vector3d position;
    AlgorithmProject::Project(pElementShapeHandle->GetPosition(), opWorkPlane.get(), uvParameter, position);

    OwnerPtr<IGraphicsPoint> opPoint = IGraphicsPoint::Create(position);
    opPoint->SetDisplayShape(PointDisplayShapeType::Circle);
    opGGrepNodeRoot->AddChild(TransferOwnership(opPoint));
    opGGrepNodeRoot->SetElementId(pElementShapeHandle->GetElementId());
    opGGrepNodeRoot->SetIsClippable(false);

    // 设置属性
    IGraphicsStyleManager* pStyleManager = GetDocument()->GetGraphicsStyleManager();
    if (pStyleManager)
    {
        ElementId gstyleId = pStyleManager->GetGraphicsStyleIdByCategoryUid(BuiltInCategoryUniIdentities::BICU_AUXILIARY_ELEMENT);
        opGGrepNodeRoot->SetGraphicsStyleId(gstyleId);
    }

    return opGGrepNodeRoot;
}

void ElevationViewSymbolNewGripPointBehavior::ReportParents(IElementParentReporter& reporter) const
{
    reporter.ReportWeak(GetModelViewId());
}

void ElevationViewSymbolNewGripPointBehavior::UpdatePosition()
{
    IElementShapeHandle* pElementShapeHandle = GetElementShapeHandle();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pElementShapeHandle != nullptr, L"invalid pElementShapeHandle",L"GDMPLab",L"2024-03-30");

    const IElement* pOwnerElement = GetMasterElement();

    //注：这里必须调用const版本的pOwnerElement，否则会引起事务外修改Element的DBG_WARN
    const IElementPositionPoints* pPositionPoints = pOwnerElement->GetPositionPoints();
    if (pPositionPoints)
    {
        int positionIndex = pElementShapeHandle->GetPositionIndexInMasterElement();
        Vector3d pos = pPositionPoints->GetControlPoint(positionIndex);
        pElementShapeHandle->SetPosition(pos);
    }
}

void ElevationViewSymbolNewGripPointBehavior::GetNearestPoint(Vector3d& nearPoint) const
{
    IElementShapeHandle* pElementShapeHandle = GetElementShapeHandle();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pElementShapeHandle != nullptr, L"invalid pElementShapeHandle",L"GDMPLab",L"2024-03-30");
    nearPoint = pElementShapeHandle->GetPosition();
}

bool ElevationViewSymbolNewGripPointBehavior::GetHandleCommandString(const IObject* commandEnvironment, std::wstring& commandStr, CommandParameters& cmdParams) const
{
    return false;
}
#pragma endregion GripPointBehavior

#pragma region ViewSpecificShapeBehavior

BEGIN_UPGRADE_CLASS(gcmp, ElevationViewSymbolNewViewSpecificShapeComponent, 2)
ADD_OWNERPTR_IDB_PROPERTY(OwnerPtr<IRenderPriorityOffsetProvider>, RenderPriorityOffsetProvider)
END_UPGRADE_CLASS

BEGIN_UPGRADE_CLASS(gcmp, ElevationViewSymbolNewViewSpecificShapeComponent, 3)
ADD_OWNERPTR_IDB_PROPERTY(OwnerPtr<IGraphicsNodeVisibilityCustomizer>, GraphicsNodeVisibilityCustomizer)
END_UPGRADE_CLASS

DBOBJECT_DATA_DEFINE(ElevationViewSymbolNewViewSpecificShapeComponent)
{
    m_pOwnerElement = nullptr;
    m_GraphicsNodeVisibilityCustomizer = nullptr;
}

bool ElevationViewSymbolNewViewSpecificShapeComponent::SetOwnerElement(IElement* pOwnerElement)
{ 
    m_pOwnerElement = pOwnerElement;
    IGraphicsNodeVisibilityCustomizer* pCustomizer = m_GraphicsNodeVisibilityCustomizer.get();
    if (pCustomizer)
    {
        pCustomizer->SetOwnerElement(pOwnerElement);
    }
    return true;
}

bool ElevationViewSymbolNewViewSpecificShapeComponent::IsVisibleInModelView(const IModelView* pModelView) const
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pModelView != nullptr, L"Invalid pModelView",L"GDMPLab",L"2024-03-30");

    const IElement* pElem = GetOwnerElement();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pElem != nullptr, L"pElem is nullptr",L"GDMPLab",L"2024-03-30");
    if (pModelView->GetDocument() != pElem->GetDocument()) // 不是同文档的不可见
    {
        return false;
    }

    if (PlanViewType == pModelView->GetUserDataId())
    {
        return true;
    }
    return false;
}

OwnerPtr<IGraphicsElementShape> ElevationViewSymbolNewViewSpecificShapeComponent::CreateViewSpecificElementShape(const IModelView* pModelView) const
{
    const ElevationViewSymbolNew *pElevatoinViewSymbol = GetElevationViewSymbolByOwnerElement(GetOwnerElement());
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pElevatoinViewSymbol != nullptr, L"Invalid pElevatoinViewSymbol",L"GDMPLab",L"2024-03-30");

    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pModelView != nullptr, L"Invalid pModelView",L"GDMPLab",L"2024-03-30");
    return pElevatoinViewSymbol->CreateModelViewElementShape(pModelView);
}

void ElevationViewSymbolNewViewSpecificShapeComponent::SetRenderPriorityOffsetProvider(OwnerPtr<IRenderPriorityOffsetProvider> opProvider)
{
    SetRenderPriorityOffsetProvider__(TransferOwnership(opProvider));
}

const IRenderPriorityOffsetProvider* ElevationViewSymbolNewViewSpecificShapeComponent::GetRenderPriorityOffsetProvider() const
{
    return GetRenderPriorityOffsetProvider__().get();
}

IRenderPriorityOffsetProvider* ElevationViewSymbolNewViewSpecificShapeComponent::GetRenderPriorityOffsetProvider()
{
    return GetRenderPriorityOffsetProviderFW__().get();
}

void ElevationViewSymbolNewViewSpecificShapeComponent::SetGraphicsNodeVisibilityCustomizer(OwnerPtr<IGraphicsNodeVisibilityCustomizer> opCustomizer)
{
    if (opCustomizer)
    {
        opCustomizer->SetOwnerElement(GetOwnerElement());
    }
    SetGraphicsNodeVisibilityCustomizer__(TransferOwnership(opCustomizer));
}

const IGraphicsNodeVisibilityCustomizer* ElevationViewSymbolNewViewSpecificShapeComponent::GetGraphicsNodeVisibilityCustomizer() const
{
    return GetGraphicsNodeVisibilityCustomizer__().get();
}

IGraphicsNodeVisibilityCustomizer* ElevationViewSymbolNewViewSpecificShapeComponent::GetGraphicsNodeVisibilityCustomizer()
{
    return GetGraphicsNodeVisibilityCustomizerFW__().get();
}

#pragma endregion ViewSpecificShapeBehavior

#pragma region UiManipulatorComponent

DBOBJECT_DATA_DEFINE(ElevationViewSymbolNewUiManipulatorComponent)
{
    m_pOwnerElement = nullptr;
}

ElementId ElevationViewSymbolNewUiManipulatorComponent::CreateGripPoint(ElevationViewSymbolNewAuxiliaryType type, const ElementId& modelviewId) const
{
    const IGenericElement* pGenericElement = quick_cast<IGenericElement>(m_pOwnerElement);
    DBG_WARN_AND_RETURN_UNLESS(pGenericElement != nullptr, ElementId::InvalidID, L"invalid pGenericElement",L"GDMPLab",L"2024-03-30");

    const IElementPositionPoints* pOwnerPositionPoints = pGenericElement->GetPositionPoints();
    Vector3d pos = pOwnerPositionPoints ? pOwnerPositionPoints->GetControlPoint((int)type) : Vector3d::Zero;

    OwnerPtr<IElementShapeHandleBehavior> pGripPointBehavior = ElevationViewSymbolNewGripPointBehavior::Create(m_pOwnerElement->GetDocument(), modelviewId);

    IElementShapeHandle* pGripPoint = IElementShapeHandle::Create(
        TransferOwnership(pGripPointBehavior),
        pGenericElement->GetElementId(),
        pos, static_cast<int>(type));
    DBG_WARN_AND_RETURN_UNLESS(pGripPoint != nullptr, ElementId::InvalidID, L"invalid pGripPoint",L"GDMPLab",L"2024-03-30");

    return pGripPoint->GetElementId();
}

ElementId ElevationViewSymbolNewUiManipulatorComponent::CreateBorder(const gcmp::ElementId& modelviewId) const
{
    const IGenericElement* pGenericElement = quick_cast<IGenericElement>(m_pOwnerElement);
    DBG_WARN_AND_RETURN_UNLESS(pGenericElement != nullptr, ElementId::InvalidID, L"invalid pGenericElement",L"GDMPLab",L"2024-03-30");

    //borderPos并不是必需数据，只是调用IElementShapeHandle::Create（）设置进去的，同时还为了后续调用UpdatePosition()以更新IElementShapeHandle。borderPos不是视点位置。
    Vector3d borderPos;

    OwnerPtr<IElementShapeHandleBehavior> pBorderBehavior = ElevationViewSymbolNewBorderBehavior::Create(m_pOwnerElement->GetDocument(), modelviewId);

    IElementShapeHandle* pBorder = IElementShapeHandle::Create(
        TransferOwnership(pBorderBehavior),
        pGenericElement->GetElementId(),
        borderPos, static_cast<int>(ElevationViewSymbolNewAuxiliaryType::Border));
    DBG_WARN_AND_RETURN_UNLESS(pBorder != nullptr, ElementId::InvalidID, L"invalid pBorder",L"GDMPLab",L"2024-03-30");

    return pBorder->GetElementId();
}

#pragma endregion UiManipulatorComponent

#pragma region TransformationComponent
DBOBJECT_DATA_DEFINE(ElevationViewSymbolNewTransformationComponent)
{
    m_pOwnerElement = nullptr;
}

bool ElevationViewSymbolNewTransformationComponent::CanBeMoved(std::wstring* explanation) const
{
    const IElement* pElement = GetOwnerElement();
    if (pElement == nullptr)
        return true;

    return pElement->GetStatus()->CanBeMoved();
}

bool ElevationViewSymbolNewTransformationComponent::Translate(const IElementMoveContext& moveContext)
{
    Vector3d moveDir = moveContext.GetMoveVector();
    Matrix4d translationMat;
    translationMat.MakeTranslate(moveDir.X(), moveDir.Y(), moveDir.Z());
    return this->Transform(translationMat);
}

bool ElevationViewSymbolNewTransformationComponent::Transform(const Matrix4d& matrix)
{
    IElement *pOwnerElement = GetOwnerElement();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pOwnerElement, L"Invalid pOwnerElement",L"GDMPLab",L"2024-03-30");

    ElevationViewSymbolNew* pElevatoinViewSymbol = GetElevationViewSymbolByOwnerElementFW(pOwnerElement);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pElevatoinViewSymbol, L"invalid pElevatoinViewSymbol",L"GDMPLab",L"2024-03-30");

    pElevatoinViewSymbol->MakeTransform(matrix);

    //触发所有辅助对象关联更新
    std::vector<ElementId> vecGripPointIds = AuxiliaryElementUtils::GetAuxiliaryElements(pOwnerElement);
    pOwnerElement->GetDocument()->GetRegenerator()->ForceRegeneratingElements(vecGripPointIds);

    return true;
}
#pragma endregion TransformationComponent

#pragma region ParametersCustomizer
DBOBJECT_DATA_DEFINE(ElevationViewSymbolNewParametersCustomizer)
{
    m_pOwnerElement = nullptr;
}

OwnerPtr<IParameter> ElevationViewSymbolNewParametersCustomizer::GetNativeParameter(int paramDefId) const
{
    const IElementParameters* pElementParameters = GetElevationModelViewParameters();
    if (!pElementParameters) {
        return nullptr;
    }

    return pElementParameters->GetNativeParameter(paramDefId);
}

bool ElevationViewSymbolNewParametersCustomizer::SetNativeParameter(const IParameter *param, 
    std::wstring* errorMsg)
{
    IElementParameters* pElementParameters = GetElevationModelViewParameters();
    if (!pElementParameters)
        return false;
    return pElementParameters->SetNativeParameter(param, errorMsg);
}

void ElevationViewSymbolNewParametersCustomizer::ReportParameterDefinitions(std::vector<int>* pParamDefIds) const
{
    const IElementParameters* pElementParameters = GetElevationModelViewParameters();
    if (!pElementParameters)
        return;
    return pElementParameters->ReportParameterDefinitions(pParamDefIds);
}

bool ElevationViewSymbolNewParametersCustomizer::IsParameterModifiable(int parameterId) const
{
    const IElementParameters* pElementParameters = GetElevationModelViewParameters();
    if (!pElementParameters)
        return false;
    return pElementParameters->IsParameterModifiable(parameterId);
}

IElementParameters* ElevationViewSymbolNewParametersCustomizer::GetElevationModelViewParameters()
{
    IModelView* pElevationModelView = GetElevationModelViewByElevationViewSymbolOwnerElement(GetOwnerElement());
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pElevationModelView, L"Invalid pElevationModelView",L"GDMPLab",L"2024-03-30");

    return pElevationModelView->GetElementParameters();
}

const IElementParameters* ElevationViewSymbolNewParametersCustomizer::GetElevationModelViewParameters() const
{
    IModelView* pElevationModelView = GetElevationModelViewByElevationViewSymbolOwnerElement(GetOwnerElement());
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pElevationModelView, L"Invalid pElevationModelView",L"GDMPLab",L"2024-03-30");

    return pElevationModelView->GetElementParameters();
}
#pragma endregion ParametersCustomizer

#pragma region NameParameterOverride

DBOBJECT_DATA_DEFINE(ElevationViewSymbolNewNameParameterOverride)
{
    m_pOwnerElement = nullptr;
}

DEFINE_MODEL_VIEW_SYMBOL_NEW_PARAMETER_OVERRID_METHODS(ElevationViewSymbolNewNameParameterOverride);

const UniIdentity& ElevationViewSymbolNewNameParameterOverride::GetUidForParameterOverride() const
{
    return PARAMETER_UID(ElementNameBuiltInParameter);
}

#pragma endregion NameParameterOverride

#pragma region RegenerationBehavior

DBOBJECT_DATA_DEFINE(ElevationViewSymbolNewRegenerationBehavior)
{
    m_opOwnerElement = nullptr;
    m_ElementRegenerationBehavior = IElementRegenerationComponent::CreateDefaultRegenerationComponent();
}

ElevationViewSymbolNewRegenerationBehavior::ElevationViewSymbolNewRegenerationBehavior(IElement* pElement)
{
    m_opOwnerElement = pElement;
    m_ElementRegenerationBehavior = IElementRegenerationComponent::CreateDefaultRegenerationComponent();
}

bool ElevationViewSymbolNewRegenerationBehavior::SetOwnerElement(IElement* pOwnerElement)
{
    m_opOwnerElement = pOwnerElement;
    if (m_ElementRegenerationBehavior.get())
        m_ElementRegenerationBehavior->SetOwnerElement(pOwnerElement);
    return true;
}

bool ElevationViewSymbolNewRegenerationBehavior::CanHaveRegenData() const
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(m_ElementRegenerationBehavior, L"m_ElementRegenerationBehavior无效",L"GDMPLab",L"2024-03-30");
    return m_ElementRegenerationBehavior->CanHaveRegenData();
}

bool ElevationViewSymbolNewRegenerationBehavior::CanHaveCalculators() const
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(m_ElementRegenerationBehavior, L"m_ElementRegenerationBehavior无效",L"GDMPLab",L"2024-03-30");
    return m_ElementRegenerationBehavior->CanHaveCalculators();
}

DECLARE_CALCULATOR_CREATOR(ElevationViewSymbolNewRegenerationCalculator);
void ElevationViewSymbolNewRegenerationBehavior::GetCalculators(ICalculatorCollection* calculators) const
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_ElementRegenerationBehavior, L"m_ElementRegenerationBehavior无效",L"GDMPLab",L"2024-03-30");
    m_ElementRegenerationBehavior->GetCalculators(calculators);
    
    const ElevationViewSymbolNew *pSymbol = GetElevationViewSymbolByOwnerElement(m_opOwnerElement);
    RegenDataId modelViewUpdatedRengenId = pSymbol->GetModelViewRangeUpdatedRdId();

    ADD_CALCULATOR(ElevationViewSymbolNewRegenerationCalculator, GetDocument(), modelViewUpdatedRengenId);
}

IDocument * ElevationViewSymbolNewRegenerationBehavior::GetDocument() const
{
    if (!m_opOwnerElement)
    {
        return nullptr;
    }
    return m_opOwnerElement->GetDocument();
}

#pragma endregion RegenerationBehavior

